home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / brutil.arc / DDU.ASM < prev    next >
Assembly Source File  |  1988-05-10  |  27KB  |  1,491 lines

  1.     PAGE ,132
  2.     TITLE    IBM-PC Dangerous Disk Utility ver 1.0, 26-Apr-88
  3.  
  4. ; Based largely on the CHAIN program described below.
  5. ; DDU is written by Bruce Noblick, 185 Crestview Road, Columbus, Ohio 43202
  6. ; Phone: (614) 262-4564 evenings and weekends
  7. ;
  8. ; CHAIN was written by Steven Georgiades
  9. ;
  10. ; IBM-PC/XT File Chain Program
  11. ;   Will respond with a list of the disk clusters that make up the file chain
  12. ;   for the requested file.
  13. ;
  14. ;       If you are using this program and find it of value, your
  15. ;       contribution in any amount ($5.00 suggested) will be greatly
  16. ;       appreciated.  Makes checks payable to Steven M. Georgiades.
  17. ;               Thank you.
  18. ;
  19. ;       If you have any questions or comments about this or any other
  20. ;       SMG program, call or write:
  21. ;
  22. ;               Steven M. Georgiades
  23. ;               701-H South Hayward Street
  24. ;               Anaheim, CA 92804
  25. ;               (714) 826-9549
  26. ;
  27.  
  28.     IF1
  29.     INCLUDE OPTMAC.LIB
  30.     ENDIF
  31.     GENOPT    BFOPAMUV
  32. CODE    SEGMENT
  33.  
  34.     ASSUME    CS:CODE,DS:CODE,ES:CODE,SS:CODE
  35.  
  36.     ORG    5CH
  37.  
  38. FCB    LABEL    BYTE
  39.  
  40.     ORG    80H
  41.  
  42. PARAM    LABEL    BYTE
  43.  
  44.     ORG    100H
  45.  
  46. CHAIN:    JMP    BEGIN
  47.  
  48. ANDSTR    DB    ", $"
  49. ORMSG    DB    'Stack Overrun xxxxx',13,10,'$'
  50. ME1MSG    DB    'is already unmarked (free)',13,10,'$'
  51. ME2MSG    DB    'is already marked bad',13,10,'$'
  52. ME3MSG    DB    'is in use by a file',13,10,'$'
  53. ME4MSG    DB    'is reserved',13,10,'$'
  54. UMMSG    DB    'has been unmarked (freed)',13,10,'$'
  55. MKMSG    DB    'has been marked bad',13,10,'$'
  56. VERMSG    DB    'Verify marked xxxxx clusters bad',13,10,'$'
  57. VEREM1    DB    'Sector xxxxx of system area is bad',13,10,'$'
  58. BDMSG1    DB    'Bad      $'
  59. FRMSG1    DB    'Free     $'
  60. ALMSG1    DB    'Allocated$'
  61. FRMSG2    DB    ' Clusters on drive x:',13,10,10,'$'
  62. FRMSG3    DB    13,10,10
  63. FRMSG4    DB    'Total Clusters = xxxxx',13,10,10
  64. FRMSG5    DB    'Total Bytes = xxxxxxxx',13,10,'$'
  65. CHMSG1    DB    "The Chain for $"
  66. CHMSG2    DB    " is:",13,10,10,"$"
  67. CHMSG3    DB    13,10,10
  68. CHMSG4    DB    "Total Clusters in File =  XXXXX",13,10,10
  69. CHMSG5    DB    "Physical File Length = XXXXXXXX",13,10
  70. CHMSG6    DB    "Logical  File Length = XXXXXXXX ("
  71. PERCENT DB    " 0.00% Waste)",13,10,"$"
  72. CLSTSTR DB    "XXXXX$"
  73. PCT100    DB    "100.0"
  74. SPECERR DB    "Invalid File or Path Specification",7,": $"
  75. DTTAB    LABEL    BYTE
  76.     DW    512
  77.     DB    1
  78.     DW    1
  79.     DB    2
  80.     DW    224
  81.     DW    2400
  82.     DB    0F9H
  83.     DW    7
  84.     DW    15
  85.     DW    2
  86.     DW    0
  87.     DW    512
  88.     DB    1
  89.     DW    1
  90.     DB    2
  91.     DW    64
  92.     DW    360
  93.     DB    0FCH
  94.     DW    2
  95.     DW    9
  96.     DW    1
  97.     DW    0
  98.     DW    512
  99.     DB    2
  100.     DW    1
  101.     DB    2
  102.     DW    112
  103.     DW    720
  104.     DB    0FDH
  105.     DW    2
  106.     DW    9
  107.     DW    2
  108.     DW    0
  109.     DW    512
  110.     DB    1
  111.     DW    1
  112.     DB    2
  113.     DW    64
  114.     DW    320
  115.     DB    0FEH
  116.     DW    1
  117.     DW    8
  118.     DW    1
  119.     DW    0
  120.     DW    512
  121.     DB    2
  122.     DW    1
  123.     DB    2
  124.     DW    112
  125.     DW    640
  126.     DB    0FFH
  127.     DW    1
  128.     DW    8
  129.     DW    2
  130.     DW    0
  131. DTMSG    DB    'Using FAT ID byte to construct disk type table',13,10,'$'
  132. TERRMSG DB    'Media Byte xxxxx not supported',7,13,10,'$'
  133. PARMSG    DB    'Parameters for drive x:',13,10,10
  134. PARMSG17 DB    'OEM Name:        xxxxxxxx',13,10
  135. PARMSG3 DB    'Bytes/Sector:       xxxxx',13,10
  136. PARMSG2 DB    'Sectors/Cluster:    xxxxx',13,10
  137. PARMSG6 DB    'Reserved Sectors:   xxxxx',13,10
  138. PARMSG5 DB    'Copies/FAT:         xxxxx',13,10
  139. PARMSG7 DB    'Entries/Directory:  xxxxx  '
  140. PARMSG8 DB    '(Sectors/Directory: xxxxx)',13,10
  141. PARMSG1 DB    'Sectors/Media:      xxxxx  '
  142. PARMSG18 DB    '(Bytes/Media:    xxxxxxxx)',13,10
  143. PARMSG16 DB    'Media Byte:         xxxxx',13,10
  144. PARMSG4 DB    'Sectors/FAT:        xxxxx',13,10
  145. PARMSG11 DB    'Sectors/Track:      xxxxx',13,10
  146. PARMSG12 DB    'Sides:              xxxxx  '
  147. PARMSG13 DB    '(Tracks:            xxxxx)',13,10
  148. PARMSG14 DB    'Hidden sectors:     xxxxx',13,10
  149. PARMSG9 DB    '(First Data Sector: xxxxx)',13,10
  150. PARMSG10 DB    '(Highest cluster:   xxxxx) '
  151. PARMSG19 DB    '(Bytes/Data:     xxxxxxxx)',13,10
  152. PARMSG15 DB    '(Ignored Sectors:   xxxxx)'
  153. CRLF    DB    13,10,"$"
  154. READERR DB    'Error Reading Drive x:',7,13,10,'$'
  155. CLSTMSG DB    'Cluster xxxxx $'
  156. ONERMSG DB    'is owned by $'
  157. BADMSG    DB    'is marked as bad',13,10,'$'
  158. FREEMSG DB    'is not in use by any file',13,10,'$'
  159. INVALID DB    'does not exist!',7,13,10,'$'
  160. LOSTMSG DB    'appears to be lost!',7,13,10,'$'
  161. RESVMSG DB    'is reserved',13,10,'$'
  162.  
  163. CLSTSEC DW    ?
  164. TOTCLST DW    ?
  165. DIR_LEN DW    ?
  166. DIRBUF    DW    ?
  167. DIRSEC    DW    ?
  168. DRIVE    DB    ?
  169. EOF    DW    0FF8H
  170. BAD    DW    ?
  171. OPFLAG    DB    0
  172. FATCOP    DB    ?
  173. FATSEC    DW    ?
  174. FATSIZE DB    3
  175. FNAME    DB 13 DUP(0)
  176. PREV    DW    ?
  177. RANGE    DB    0
  178. SECSIZE DW    ?
  179. CLUST    DW    ?
  180. RDIRLEN DW    ?
  181. NEWSTK    DW    0
  182. NEXTOP    DW    ?
  183. SIZLSB    DW    ?
  184. SIZMSB    DW    ?
  185. STRTSEC DW    ?
  186. FSPEC    DB    80 DUP(0)
  187.  
  188. BEGIN:    MOV    AH,19H                ; Get Default Drive
  189.     INT    21H
  190.     MOV    DRIVE,AL            ;   and Save
  191.     MOV    SI,OFFSET PARAM         ; Set up Pointer to Parameter
  192.     LODSB                    ; Read Parameter Length
  193.     CBW
  194.     MOV    BX,AX
  195.     MOV    BYTE PTR [SI+BX],0        ; Terminate Parameter String
  196.     CALL    STRIP
  197.     JNC    BEGIN2
  198.     JMP    ERROR
  199. BEGIN2: MOV    NEXTOP,SI
  200.     MOV    AL,DRIVE            ; Read Boot Record
  201.     MOV    CX,1
  202.     MOV    DX,0
  203.     MOV    BX,OFFSET FATBUF
  204.     INT    25H
  205.     JNC    BOOT_OK
  206.     JMP    RDERROR
  207. BOOT_OK:
  208.     POPF
  209.     CMP    BYTE PTR FATBUF,0E9H
  210.     JZ    OKTYPE
  211.     CMP    BYTE PTR FATBUF,0EBH
  212.     JZ    OKTYPE
  213.     MOV    AL,DRIVE
  214.     MOV    CX,1
  215.     MOV    DX,CX
  216.     MOV    BX,OFFSET FATBUF+128
  217.     INT    25H
  218.     JNC    CHKTYP
  219.     JMP    RDERROR
  220. CHKTYP: POPF
  221.     MOV    AL,BYTE PTR FATBUF+128
  222.     CMP    AL,BYTE PTR FATBUF+21
  223.     JZ    OKTYPE
  224.     MOV    SI,OFFSET DTTAB
  225.     MOV    CX,5
  226. TSTTYP: CMP    AL,10[SI]
  227.     JZ    MOVTYP
  228.     ADD    SI,19
  229.     LOOP    TSTTYP
  230.     MOV    AL,-9[SI]
  231.     MOV    DI,OFFSET TERRMSG+16
  232.     CALL    DEC5OUT
  233.     CALL    STRIP0
  234.     MOV    DX,OFFSET TERRMSG
  235.     JMP    ERROUT
  236. MOVTYP: MOV    DI,OFFSET FATBUF+3
  237.     MOV    AX,'  '
  238.     MOV    CX,4
  239.     REP    STOSW
  240.     MOV    CX,10
  241.     REP    MOVSW
  242.     MOV    DX,OFFSET DTMSG
  243.     CALL    DOS9
  244. OKTYPE: MOV    AX,FATBUF+11            ; Read Sector Size
  245.     MOV    SECSIZE,AX            ;   and Save
  246.     MOV    AL,BYTE PTR FATBUF+13        ; Read Sectors per Cluster
  247.     XOR    AH,AH
  248.     MOV    CLSTSEC,AX            ;   and Save
  249.     MOV    CX,FATBUF+14            ; Read # of Reserved Sectors
  250.     MOV    AL,BYTE PTR FATBUF+16        ; Read # of FAT's
  251.     MOV    BX,FATBUF+22            ; Read Sectors per FAT
  252.     MOV    FATSEC,BX
  253.     MOV    FATCOP,AL
  254.     MUL    BX                ; Calculate Total FAT Sectors
  255.     ADD    CX,AX                ; Add to Reserved Sectors
  256.     MOV    AX,FATBUF+17            ; Read Number of DIR Entries
  257.     MOV    RDIRLEN,AX
  258.     MOV    DIR_LEN,AX
  259.     PUSH    CX                ; Calculate DIR Sectors
  260.     MOV    CL,5
  261.     SHL    AX,CL
  262.     POP    CX
  263.     MOV    BX,SECSIZE
  264.     XOR    DX,DX
  265.     DIV    BX
  266.     ADD    DX,-1
  267.     ADC    AX,0
  268.     MOV    DIRSEC,AX            ; Save DIR Sectors
  269.     ADD    CX,AX                ; Add DIR Sectors to Reserved
  270.     MOV    STRTSEC,CX            ; Save in STRTSEC
  271.     MOV    AX,FATSEC            ; Calculate FAT Buffer Size
  272.     MOV    BX,SECSIZE
  273.     MUL    BX
  274.     MOV    BX,AX
  275.     ADD    AX,OFFSET FATBUF        ; Get DIR Buffer Pointer
  276.     MOV    DIRBUF,AX
  277.     MOV    AX,FATBUF+19            ; Read Total Sectors on Media
  278.     SUB    AX,CX                ; Calculate Total Data Clusters
  279.     MOV    BX,CLSTSEC
  280.     XOR    DX,DX
  281.     DIV    BX
  282.     INC    AX
  283.     MOV    TOTCLST,AX
  284.     CMP    AX,4080             ; If Necessary, Adjust FAT Size
  285.     JL    FAT_OK
  286.     MOV    FATSIZE,4
  287.     MOV    EOF,0FFF8H
  288. FAT_OK: CMP    OPFLAG,POPT
  289.     JZ    NO_FAT
  290.     JMP    FAT_OK1
  291. NO_FAT: MOV    SI,OFFSET FATBUF+3
  292.     MOV    DI,OFFSET PARMSG17+17
  293.     MOV    CX,4
  294.     REP    MOVSW
  295.     LODSW
  296.     MOV    DI,OFFSET PARMSG3+25
  297.     CALL    DEC5OUT
  298.     CALL    STRIP0
  299.     LODSB
  300.     XOR    AH,AH
  301.     MOV    DI,OFFSET PARMSG2+25
  302.     CALL    DEC5OUT
  303.     CALL    STRIP0
  304.     LODSW
  305.     MOV    DI,OFFSET PARMSG6+25
  306.     CALL    DEC5OUT
  307.     CALL    STRIP0
  308.     LODSB
  309.     XOR    AH,AH
  310.     MOV    DI,OFFSET PARMSG5+25
  311.     CALL    DEC5OUT
  312.     CALL    STRIP0
  313.     LODSW
  314.     MOV    DI,OFFSET PARMSG7+25
  315.     CALL    DEC5OUT
  316.     CALL    STRIP0
  317.     LODSW
  318.     MOV    BX,AX
  319.     MOV    DI,OFFSET PARMSG1+25
  320.     CALL    DEC5OUT
  321.     CALL    STRIP0
  322.     MOV    AX,BX
  323.     MUL    SECSIZE
  324.     MOV    DI,OFFSET PARMSG18+25
  325.     CALL    DEC8OUT
  326.     CALL    STRIP0
  327.     LODSB
  328.     XOR    AH,AH
  329.     MOV    DI,OFFSET PARMSG16+25
  330.     CALL    DEC5OUT
  331.     CALL    STRIP0
  332.     LODSW
  333.     MOV    DI,OFFSET PARMSG4+25
  334.     CALL    DEC5OUT
  335.     CALL    STRIP0
  336.     LODSW
  337.     MOV    DI,OFFSET PARMSG11+25
  338.     CALL    DEC5OUT
  339.     CALL    STRIP0
  340.     LODSW
  341.     MOV    DI,OFFSET PARMSG12+25
  342.     CALL    DEC5OUT
  343.     CALL    STRIP0
  344.     LODSW
  345.     MOV    DI,OFFSET PARMSG14+25
  346.     CALL    DEC5OUT
  347.     CALL    STRIP0
  348.     MOV    AX,DIRSEC
  349.     MOV    DI,OFFSET PARMSG8+25
  350.     CALL    DEC5OUT
  351.     CALL    STRIP0
  352.     MOV    AX,STRTSEC
  353.     MOV    DI,OFFSET PARMSG9+25
  354.     CALL    DEC5OUT
  355.     CALL    STRIP0
  356.     MOV    AX,TOTCLST
  357.     MOV    BX,AX
  358.     MOV    DI,OFFSET PARMSG10+25
  359.     CALL    DEC5OUT
  360.     CALL    STRIP0
  361.     MOV    AX,BX
  362.     DEC    AX
  363.     MUL    CLSTSEC
  364.     MUL    SECSIZE
  365.     MOV    DI,OFFSET PARMSG19+25
  366.     CALL    DEC8OUT
  367.     CALL    STRIP0
  368.     MOV    AX,FATBUF+24
  369.     MUL    FATBUF+26
  370.     MOV    BX,AX
  371.     MOV    AX,FATBUF+19
  372.     ADD    AX,FATBUF+28
  373.     DIV    BX
  374.     OR    DX,DX
  375.     JZ    NO_ADD2
  376.     INC    AX
  377.     JMP    SHORT NO_ADD3
  378. NO_ADD2:
  379.     MOV    DX,BX
  380. NO_ADD3:
  381.     MOV    DI,OFFSET PARMSG13+25
  382.     CALL    DEC5OUT
  383.     CALL    STRIP0
  384.     MOV    AX,BX
  385.     SUB    AX,DX
  386.     MOV    DI,OFFSET PARMSG15+25
  387.     CALL    DEC5OUT
  388.     CALL    STRIP0
  389.     MOV    DX,OFFSET PARMSG
  390.     JMP    CC_OK_3
  391. FAT_OK1:
  392.     MOV    AL,DRIVE            ; Read FAT
  393.     MOV    CX,FATSEC
  394.     MOV    DX,1
  395.     MOV    BX,OFFSET FATBUF
  396.     INT    25H
  397.     JNC    FAT_OK2
  398.     JMP    RDERROR
  399. FAT_OK2:
  400.     POPF
  401.     MOV    AX,EOF
  402.     DEC    AX
  403.     MOV    BAD,AX
  404.     CMP    OPFLAG,BOPT
  405.     JZ    GOTB
  406.     CMP    OPFLAG,FOPT
  407.     JZ    GOTF
  408.     CMP    OPFLAG,AOPT
  409.     JZ    GOTA
  410.     CMP    OPFLAG,MOPT
  411.     JNZ    NOTM
  412.     JMP    MARKIT
  413. NOTM:
  414.     CMP    OPFLAG,UOPT
  415.     JNZ    NOTU
  416.     JMP    UNMARK
  417. NOTU:
  418.     CMP    OPFLAG,VOPT
  419.     JNZ    NOTV
  420.     JMP    VERIFY
  421. NOTV:
  422.     CMP    OPFLAG,OOPT
  423.     JZ    RDROOT
  424.     CMP    OPFLAG,0
  425.     JZ    RDROOT
  426.     JMP    ERROR
  427. GOTB:    MOV    DX,OFFSET BDMSG1
  428.     JMP    SHORT GOTMSG
  429. GOTF:    MOV    DX,OFFSET FRMSG1
  430.     JMP    SHORT GOTMSG
  431. GOTA:    MOV    DX,OFFSET ALMSG1
  432. GOTMSG: CALL    DOS9
  433.     MOV    DX,OFFSET FRMSG2
  434.     CALL    DOS9
  435.     MOV    BX,2
  436.     XOR    CX,CX
  437. CL1:    CALL    TESTCL
  438.     JNZ    CL1
  439.     MOV    AX,BX
  440.     DEC    AX
  441.     MOV    PREV,AX
  442.     CALL    OUT_CLST
  443.     INC    CX
  444. CL1D:    CALL    TESTCL
  445.     JNZ    CL1D
  446.     MOV    AX,BX
  447.     DEC    AX
  448.     DEC    AX
  449.     INC    CX
  450.     CMP    AX,PREV
  451.     PUSHF
  452.     INC    AX
  453.     POPF
  454.     JNE    CL1G
  455.     MOV    RANGE,-1
  456.     JMP    SHORT    CL1I
  457. CL1G:    CALL    SENDEM
  458.     MOV    AX,BX
  459.     DEC    AX
  460.     CALL    OUT_CLST
  461. CL1I:    MOV    AX,BX
  462.     DEC    AX
  463.     MOV    PREV,AX
  464.     JMP    CL1D
  465. CL1J:    JMP    FINDSK
  466. RDROOT: CMP    OPFLAG,OOPT
  467.     JNZ    RDROOT2
  468.     CALL    OWNER
  469. RDROOT2:
  470.     CALL    GETROOT
  471.     MOV    SI,OFFSET FSPEC+3        ; Point to First Element of Path
  472. NEXT_FLD:
  473.     MOV    DI,OFFSET FNAME         ; Point to FileName Buffer
  474. NEXTCHAR:
  475.     LODSB                    ; Copy Path Element to FileName
  476.     CMP    AL,'\'                ;   until '\' or nul
  477.     JE    GOT_DIR
  478.     STOSB
  479.     OR    AL,AL
  480.     JE    GOT_FNM
  481.     JMP    NEXTCHAR
  482. GOT_DIR:
  483.     MOV    AL,0                ; If '\', Read Subdirectory
  484.     STOSB
  485.     CALL    READDIR
  486.     JNC    NEXT_FLD            ;   If No Error, Get Next Dir
  487.     JMP    ERROR                ;   Else Flag Error
  488. GOT_FNM:
  489.     CALL    SRCHFILE            ;   Read File DIR Info
  490.     JNC    NOERR3
  491.     JMP    ERROR                ; If Error, Say So
  492. NOERR3: MOV    AX,[BX+28]            ; Read File Length
  493.     MOV    SIZLSB,AX
  494.     MOV    DX,[BX+30]
  495.     MOV    SIZMSB,DX
  496.     MOV    DI,OFFSET CHMSG6+31        ; Convert to ASCII
  497.     CALL    DEC8OUT             ; Strip Off Leading Zeroes
  498.     CALL    STRIP0
  499.     MOV    DX,OFFSET CHMSG1        ; Output FileSpec Message
  500.     CALL    DOS9
  501.     MOV    DX,OFFSET FSPEC
  502.     CALL    ALTDOS9
  503.     MOV    DX,OFFSET CHMSG2
  504.     CALL    DOS9
  505.     MOV    BX,[BX+26]            ; Read Starting Cluster Number
  506.     XOR    CX,CX                ; Cluster Count = 0
  507.     OR    BX,BX                ; If Start Cluster = 0, Done
  508.     JZ    LASTCLST
  509.     MOV    AX,BX                ; Output First Cluster Number
  510.     CALL    OUT_CLST
  511.     MOV    PREV,BX             ; Previous Cluster = First
  512.     INC    CX                ; Cluster Count = 1
  513.     CALL    NEXTCLST            ; Get Next Cluster Number
  514.     CMP    BX,EOF                ; If Last, Skip
  515.     JNB    LASTCLST
  516. CLSTLOOP:
  517.     INC    CX                ; Increment Cluster Count
  518.     MOV    AX,PREV             ; If Cluster is Previous + 1,
  519.     INC    AX
  520.     CMP    AX,BX
  521.     JNE    CLSTOUT
  522.     MOV    RANGE,-1            ;   Set Range Flag
  523.     JMP    SHORT NEXTONE
  524. CLSTOUT:
  525.     CALL    SENDEM
  526.     CALL    OUT_CLST
  527. NEXTONE:
  528.     MOV    PREV,BX             ; Previous = Current
  529.     CALL    NEXTCLST            ; Get Next Cluster Number
  530.     CMP    BX,EOF                ; If Not EOF, Repeat
  531.     JB    CLSTLOOP
  532. FINDSK: CMP    RANGE,0             ; If Range Flag is Set,
  533.     JE    LASTCLST
  534.     MOV    AH,2                ;   Output " - "
  535.     MOV    DL,'-'
  536.     INT    21H
  537.     MOV    AX,PREV             ;   Output Last Cluster of Range
  538.     CALL    OUT_CLST
  539. LASTCLST:
  540.     CMP    OPFLAG,0
  541.     JNZ    CLSTCNT
  542.     MOV    AX,SIZMSB            ; If Size = 0, 100% Waste
  543.     OR    AX,SIZLSB
  544.     JNZ    NOT_ZERO
  545.     MOV    SI,OFFSET PCT100
  546.     MOV    DI,OFFSET PERCENT
  547.     PUSH    CX
  548.     MOV    CX,5
  549.     REP    MOVSB
  550.     POP    CX
  551.     JMP    SHORT CLSTCNT
  552. NOT_ZERO:
  553.     MOV    AX,SECSIZE            ; Calculate Percent Waste
  554.     MOV    BX,CLSTSEC
  555.     MUL    BX
  556.     MOV    BX,AX
  557.     MUL    CX
  558.     SUB    AX,SIZLSB
  559.     MOV    DX,100
  560.     MUL    DX
  561.     DIV    BX
  562.     PUSH    DX
  563.     XOR    DX,DX
  564.     DIV    CX
  565.     PUSH    DX
  566.     MOV    DI,OFFSET PERCENT+2        ; Convert Percent to ASCII
  567.     CALL    DEC2OUT
  568.     CALL    STRIP0
  569.     POP    AX
  570.     MUL    BX
  571.     POP    DI
  572.     ADD    AX,DI
  573.     ADC    DX,0
  574.     DIV    CX
  575.     MOV    DX,100
  576.     MUL    DX
  577.     DIV    BX
  578.     MOV    DI,OFFSET PERCENT+5
  579.     CALL    DEC2OUT
  580. CLSTCNT:
  581.     MOV    AX,CX                ; Convert Cluster Count to ASCII
  582.     MOV    DI,OFFSET CHMSG4+31
  583.     CMP    OPFLAG,0
  584.     JZ    CC_OK
  585.     MOV    DI,OFFSET FRMSG4+22
  586. CC_OK:    CALL    DEC5OUT
  587.     CALL    STRIP0                  ; Strip Off Leading Zeroes
  588.     MOV    AX,CLSTSEC              ; Calculate Physical File Size
  589.     MUL    CX
  590.     MOV    CX,SECSIZE
  591.     MUL    CX
  592.     MOV    DI,OFFSET CHMSG5+31        ; Convert to ASCII
  593.     CMP    OPFLAG,0
  594.     JZ    CC_OK_2
  595.     MOV    DI,OFFSET FRMSG5+22        ; Convert to ASCII
  596. CC_OK_2:
  597.     CALL    DEC8OUT
  598.     CALL    STRIP0                  ; Strip Off Leading Zeroes
  599.     MOV    DX,OFFSET CHMSG3        ; Output Trailer Message
  600.     CMP    OPFLAG,0
  601.     JZ    CC_OK_3
  602.     MOV    DX,OFFSET FRMSG3        ; Output Trailer Message
  603. CC_OK_3:
  604.     CALL    DOS9
  605.     MOV    SI,NEXTOP
  606.     CALL    STRIP
  607.     JC    CC_OK_4
  608.     JMP    BEGIN2
  609. CC_OK_4:
  610.     MOV    AX,4C00H            ; Exit to DOS
  611.     INT    21H
  612.  
  613. TESTCL: CMP    BX,TOTCLST
  614.     JA    TC3
  615.     PUSH    BX
  616.     CALL    NEXTCLST
  617.     MOV    AX,BX
  618.     POP    BX
  619.     INC    BX
  620.     CMP    OPFLAG,BOPT
  621.     JZ    TC1
  622.     CMP    OPFLAG,FOPT
  623.     JZ    TC1A
  624.     OR    AX,AX
  625.     JZ    TC0
  626.     CMP    AX,BAD
  627.     JZ    TC0
  628.     CMP    AX,AX
  629.     JMP    SHORT TC2
  630. TC0:    SUB    AX,AX
  631.     INC    AX
  632.     JMP    SHORT TC2
  633. TC1A:    OR    AX,AX
  634.     JMP    SHORT    TC2
  635. TC1:    CMP    AX,BAD
  636. TC2:    RET
  637. TC3:    JMP    CL1J
  638.  
  639. ERROR:    MOV    DX,OFFSET SPECERR        ; Output Error Message
  640.     CALL    DOS9
  641.     MOV    DX,OFFSET PARAM         ; Output FileSpec
  642.     CALL    ALTDOS9
  643.     JMP    CRLFX
  644.  
  645. OWNER:    CALL    GETCLST
  646.     CALL    NEXTCLST
  647.     OR    BX,BX
  648.     JNZ    NOT_FREE
  649.     MOV    DX,OFFSET FREEMSG
  650.     JMP    CC_OK_3
  651. NOT_FREE:
  652.     MOV    AX,EOF
  653.     CMP    BX,AX
  654.     JAE    CLSTGOOD
  655.     DEC    AX
  656.     CMP    BX,AX
  657.     JNE    NOT_BAD
  658.     MOV    DX,OFFSET BADMSG
  659.     JMP    CC_OK_3
  660. NOT_BAD:
  661.     SUB    AX,7
  662.     CMP    BX,AX
  663.     JB    CLSTGOOD
  664.     MOV    DX,OFFSET RESVMSG
  665.     JMP    CC_OK_3
  666. RDERROR:
  667.     POPF
  668.     MOV    AL,DRIVE
  669.     ADD    AL,'A'
  670.     MOV    READERR+20,AL
  671.     MOV    DX,OFFSET READERR
  672. ERROUT: CALL    DOS9
  673.     MOV    AX,4C01H            ; Exit to DOS
  674.     INT    21H
  675. CLSTGOOD:
  676.     MOV    AX,CLUST
  677. CLSTBACK:
  678.     MOV    BX,AX
  679.     CALL    PREVCLST
  680.     OR    AX,AX
  681.     JNZ    CLSTBACK
  682.     MOV    CLUST,BX
  683.     CALL    GETROOT
  684.     SUB    BX,BX
  685.     MOV    NEWSTK,BX
  686.     CALL    PUSHBX
  687. LOOK1:    CALL    SRCHCLST
  688.     JNC    FOUND
  689.     MOV    SI,DIRBUF
  690.     MOV    CX,DIR_LEN
  691. LOOK2:    CALL    FINDDIR
  692.     JC    LOOK3
  693.     MOV    BX,26[SI]
  694.     CALL    PUSHBX
  695.     ADD    SI,32
  696.     LOOP    LOOK2
  697. LOOK3:    CALL    POPBX
  698.     JZ    BADCLST
  699.     CALL    GETADIR
  700.     JMP    LOOK1
  701. BADCLST:
  702.     MOV    DX,OFFSET LOSTMSG
  703.     JMP    CC_OK_3
  704. FOUND:    SUB    BX,BX
  705.     MOV    NEWSTK,BX
  706.     CALL    PUSHBX
  707.     MOV    BX,CLUST
  708.     CALL    PUSHBX
  709.     MOV    SI,DIRBUF
  710.     CMP    BYTE PTR [SI],'.'
  711.     JNZ    GOTEM
  712.     MOV    BX,26[SI]
  713.     CALL    PUSHBX
  714. BACKTRACK:
  715.     MOV    BX,58[SI]
  716.     CALL    PUSHBX
  717.     JZ    ENDBACK
  718.     PUSH    SI
  719.     CALL    GETADIR
  720.     POP    SI
  721.     JMP    BACKTRACK
  722. ENDBACK:
  723.     CALL    POPBX
  724.     CALL    GETROOT
  725. GOTEM:    MOV    DI,OFFSET FSPEC+2
  726. UNDO:    CALL    POPBX
  727.     INT    3
  728.     JZ    UNDONE
  729.     MOV    CLUST,BX
  730.     CALL    SRCHCLST
  731.     MOV    SI,OFFSET FNAME
  732.     MOV    AL,'\'
  733.     STOSB
  734.     CALL    MOVSTR
  735.     CALL    POPBX
  736.     CALL    PUSHBX
  737.     JZ    UNDONE
  738.     PUSH    DI
  739.     MOV    BX,CLUST
  740.     CALL    GETADIR
  741.     POP    DI
  742.     DEC    DI
  743.     JMP    UNDO
  744. UNDONE:     MOV    DX,OFFSET ONERMSG
  745.     CALL    DOS9
  746.     MOV    DX,OFFSET FSPEC
  747.     CALL    ALTDOS9
  748. CRLFX:    MOV    DX,OFFSET CRLF
  749. DOS9:    MOV    AH,9
  750.     INT    21H
  751.     RET
  752.  
  753. ALTDOS9:
  754.     PUSH    SI
  755.     PUSH    DX
  756.     MOV    SI,DX
  757. AD1:    LODSB
  758.     OR    AL,AL
  759.     JZ    AD2
  760.     MOV    DL,AL
  761.     MOV    AH,2
  762.     INT    21H
  763.     JMP    AD1
  764. AD2:    POP    DX
  765.     POP    SI
  766.     RET
  767.  
  768. MARKIT: CALL    GETCLST
  769.     CALL    NEXTCLST
  770.     OR    BX,BX
  771.     JZ    MARKCOM
  772. MARKERR:
  773.     OR    BX,BX
  774.     JZ    ME1
  775.     MOV    AX,BAD
  776.     CMP    BX,AX
  777.     JE    ME2
  778.     JA    ME3
  779.     SUB    AX,7
  780.     CMP    BX,AX
  781.     JB    ME3
  782.     MOV    DX,OFFSET ME4MSG
  783.     JMP    CC_OK_3
  784. ME1:    MOV    DX,OFFSET ME1MSG
  785.     JMP    CC_OK_3
  786. ME2:    MOV    DX,OFFSET ME2MSG
  787.     JMP    CC_OK_3
  788. ME3:    MOV    DX,OFFSET ME3MSG
  789.     JMP    CC_OK_3
  790. UNMARK: CALL    GETCLST
  791.     CALL    NEXTCLST
  792.     CMP    BX,BAD
  793.     JNZ    MARKERR
  794. MARKCOM:
  795.     MOV    AX,BX
  796.     MOV    BX,CLUST
  797.     XOR    AX,BAD
  798.     PUSH    AX
  799.     CALL    SETCLST
  800.     CALL    WRT_FAT
  801.     POP    AX
  802.     OR    AX,AX
  803.     MOV    DX,OFFSET UMMSG
  804.     JZ    UMMCOM
  805.     MOV    DX,OFFSET MKMSG
  806. UMMCOM: JMP    CC_OK_3
  807.  
  808. VERIFY: MOV    OPFLAG,0
  809.     MOV    AL,DRIVE
  810.     MOV    CX,STRTSEC
  811.     MOV    DX,0
  812.     MOV    BX,DIRBUF
  813. VERLP1: PUSH    AX
  814.     PUSH    BX
  815.     PUSH    CX
  816.     PUSH    DX
  817.     MOV    CX,1
  818.     INT    25H
  819.     JC    VERER1
  820.     POPF
  821.     POP    DX
  822.     POP    CX
  823.     POP    BX
  824.     POP    AX
  825.     INC    DX
  826.     LOOP    VERLP1
  827.     MOV    BX,2
  828.     MOV    CX,0
  829. VERLP2: CMP    BX,TOTCLST
  830.     JA    VERLP2X
  831.     CLC
  832.     PUSH    BX
  833.     MOV    DI,DIRBUF
  834.     CALL    READCLST
  835.     POP    BX
  836.     JC    VERMRK
  837. VERNXT: INC    BX
  838.     JMP    VERLP2
  839. VERER1: MOV    AX,DX
  840.     MOV    DI,OFFSET VEREM1+12
  841.     CALL    DEC5OUT
  842.     CALL    STRIP0
  843.     MOV    DX,OFFSET VEREM1
  844.     ADD    SP,10
  845.     JMP    CC_OK_3
  846. VERLP2X:
  847.     OR    CX,CX
  848.     JZ    VERLP2Y
  849.     PUSH    CX
  850.     CALL    WRT_FAT
  851.     POP    CX
  852. VERLP2Y:
  853.     MOV    AX,CX
  854.     MOV    DI,OFFSET VERMSG+19
  855.     CALL    DEC5OUT
  856.     CALL    STRIP0
  857.     MOV    DX,OFFSET VERMSG
  858.     JMP    CC_OK_3
  859. VERMRK: MOV    CLUST,BX
  860.     MOV    AX,BX
  861.     MOV    DI,OFFSET CLSTMSG+13
  862.     CALL    DEC5OUT
  863.     CALL    STRIP0
  864.     MOV    DX,OFFSET CLSTMSG
  865.     CALL    DOS9
  866.     CALL    NEXTCLST
  867.     OR    BX,BX
  868.     JNZ    VERERR
  869.     MOV    AX,BAD
  870.     MOV    BX,CLUST
  871.     CALL    SETCLST
  872.     INC    CX
  873.     MOV    DX,OFFSET MKMSG
  874.     CALL    DOS9
  875.     JMP    VERNXT
  876. VERERR: MOV    AX,BAD
  877.     CMP    BX,AX
  878.     JE    VE2
  879.     JA    VE3
  880.     SUB    AX,7
  881.     CMP    BX,AX
  882.     JB    VE3
  883.     MOV    DX,OFFSET ME4MSG
  884. VE4:    CALL    DOS9
  885.     MOV    BX,CLUST
  886.     JMP    VERNXT
  887. VE2:    MOV    DX,OFFSET ME2MSG
  888.     JMP    VE4
  889. VE3:    MOV    DX,OFFSET ME3MSG
  890.     JMP    VE4
  891.  
  892. WRT_FAT:
  893.     MOV    AL,DRIVE
  894.     MOV    CX,FATSEC
  895.     MOV    DX,1
  896.     MOV    AH,FATCOP
  897.     MOV    BX,OFFSET FATBUF
  898. FATLOOP:
  899.     PUSH    AX
  900.     PUSH    BX
  901.     PUSH    CX
  902.     PUSH    DX
  903.     INT    26H
  904.     POPF
  905.     POP    DX
  906.     POP    CX
  907.     POP    BX
  908.     POP    AX
  909.     ADD    DX,CX
  910.     DEC    AH
  911.     JNZ    FATLOOP
  912.     MOV    AH,13
  913.     INT    21H
  914.     RET
  915.  
  916. SETCLST:
  917.     PUSH    BX
  918.     CMP    FATSIZE,3
  919.     JZ    SETC_12
  920.     SHL    BX,1
  921.     MOV    FATBUF[BX],AX
  922.     JMP    SHORT SETC_DONE
  923. SETC_12:
  924.     PUSH    CX
  925.     MOV    CX,BX
  926.     SHL    CX,1
  927.     ADD    BX,CX
  928.     SHR    BX,1
  929.     MOV    CX,0F000H
  930.     JNC    SETC_OK
  931.     MOV    CL,4
  932.     SHL    AX,CL
  933.     MOV    CX,0FH
  934. SETC_OK:
  935.     AND    FATBUF[BX],CX
  936.     OR    FATBUF[BX],AX
  937.     POP    CX
  938. SETC_DONE:
  939.     POP    BX
  940.     RET
  941.  
  942. GETCLST:
  943.     MOV    SI,OFFSET FSPEC+3
  944.     MOV    OPFLAG,0
  945. OWNER1: MOV    DI,SI
  946. OWNER2: LODSB
  947.     CMP    AL,'\'
  948.     JZ    OWNER1
  949.     OR    AL,AL
  950.     JNZ    OWNER2
  951.     MOV    SI,DI
  952.     CALL    GET_WORD
  953.     MOV    CLUST,DX
  954.     MOV    BX,DX
  955.     MOV    AX,BX
  956.     MOV    DI,OFFSET CLSTMSG+13
  957.     CALL    DEC5OUT
  958.     CALL    STRIP0
  959.     MOV    DX,OFFSET CLSTMSG
  960.     CALL    DOS9
  961.     CMP    BX,TOTCLST
  962.     JA    CLSTBAD
  963.     CMP    BX,2
  964.     JB    CLSTBAD
  965.     RET
  966. CLSTBAD:
  967.     MOV    DX,OFFSET INVALID
  968.     JMP    CC_OK_3
  969.  
  970. GETROOT:
  971.     MOV    AL,DRIVE            ; Read Root Directory
  972.     MOV    CX,DIRSEC
  973.     MOV    DX,STRTSEC
  974.     SUB    DX,CX
  975.     MOV    BX,DIRBUF
  976.     INT    25H
  977.     POPF
  978.     MOV    AX,RDIRLEN
  979.     MOV    DIR_LEN,AX
  980.     RET
  981.  
  982. SENDEM: CMP    RANGE,0             ; Else
  983.     JE    SE1                ;   If Range Flag is Set,
  984.     MOV    AH,2                ;     Output " - "
  985.     MOV    DL,'-'
  986.     INT    21H
  987.     MOV    AX,PREV             ;     Output Last Clstr in Range
  988.     CALL    OUT_CLST
  989.     MOV    RANGE,0             ;     Reset Range Flag
  990. SE1:    MOV    DX,OFFSET ANDSTR        ;   Output ",  "
  991.     CALL    DOS9
  992.     MOV    AX,BX                ; Output Cluster Number
  993.     RET
  994.  
  995. SRCHFILE:
  996.     PUSH    AX                ; Save Register
  997.     PUSH    CX
  998.     PUSH    DI
  999.     PUSH    SI
  1000.     CMP    FNAME,'.'            ; If Filename Starts with '.',
  1001.     JNE    SRCHFIL2
  1002.     MOV    SI,OFFSET FNAME         ;   Copy Filename to FCB
  1003.     MOV    DI,OFFSET FCB+1
  1004.     MOV    CX,11
  1005. SRCHFIL1:
  1006.     LODSB
  1007.     STOSB
  1008.     OR    AL,AL
  1009.     LOOPNZ    SRCHFIL1
  1010.     INC    CX                ;   and Pad With Spaces
  1011.     DEC    DI
  1012.     MOV    AL,' '
  1013.     REP    STOSB
  1014.     JMP    SHORT SRCHFIL3
  1015. SRCHFIL2:
  1016.     MOV    AX,2900H            ; Else Parse Filename
  1017.     MOV    SI,OFFSET FNAME
  1018.     MOV    DI,OFFSET FCB
  1019.     INT    21H
  1020. SRCHFIL3:
  1021.     MOV    DI,OFFSET FCB+1         ; Point to Filename in FCB
  1022.     MOV    SI,DIRBUF            ; Point to Start of DIRBUF
  1023.     MOV    CX,DIR_LEN            ; Load DIR Length
  1024.     JCXZ    SRCHFIL5              ; If Zero, Not Found
  1025. SRCHFIL4:
  1026.     PUSH    CX                ; Save Registers
  1027.     PUSH    DI
  1028.     PUSH    SI
  1029.     MOV    CX,11                ; Compare Filename
  1030.     REPE    CMPSB
  1031.     POP    SI                ; Restore Registers
  1032.     POP    DI
  1033.     POP    CX
  1034.     JE    SRCHFIL6            ; If Match, Found
  1035.     ADD    SI,32                ; Else Next DIR Entry
  1036.           LOOP    SRCHFIL4                      ; and Repeat
  1037. SRCHFIL5:
  1038.     STC                    ; Set Error Flag
  1039.     JMP    SHORT SRCHFIL7            ; Done
  1040. SRCHFIL6:
  1041.     MOV    BX,SI                ; Set Pointer to DIR Entry
  1042.     CLC                    ; Clear Error Flag
  1043. SRCHFIL7:
  1044.     POP    SI                ; Restore Registers
  1045.     POP    DI
  1046.     POP    CX
  1047.     POP    AX
  1048.     RET                    ; Done
  1049.  
  1050. READDIR:
  1051.     PUSH    CX                ; Save Registers
  1052.     PUSH    DI
  1053.     PUSH    SI
  1054.     CALL    SRCHFILE            ; Search for DIR
  1055.     JC    READDIR3            ; If Not Found, Error
  1056.     MOV    BX,[BX+26]            ; Get Starting Cluster Number
  1057.     OR    BX,BX                ; If Start Cluster = 0, Error
  1058.     STC
  1059.     JZ    READDIR3
  1060.     CALL    GETADIR
  1061. READDIR3:
  1062.     POP    SI                ; Restore Registers
  1063.     POP    DI
  1064.     POP    CX
  1065.     RET                    ; Done
  1066.  
  1067. GETADIR:
  1068.     MOV    DIR_LEN,0            ; DIR Length = 0
  1069.     MOV    AX,SECSIZE            ; Calculate DIR Entries/Cluster
  1070.     MUL    CLSTSEC
  1071.     MOV    CL,5
  1072.     SHR    AX,CL
  1073.     MOV    CX,AX
  1074.     MOV    DI,DIRBUF              ; Point to DIR Buffer
  1075. READLOOP:
  1076.     CALL    READCLST            ; Read Cluster
  1077.     ADD    DIR_LEN,CX            ; Increment DIR Length
  1078.     CMP    BX,EOF                ; If Not Last Cluster,
  1079.     JB    READLOOP            ;   Get Next Cluster
  1080.     RET
  1081.  
  1082. PUSHBX: CMP    NEWSTK,4096
  1083.     JZ    PPBXR
  1084.     PUSH    AX
  1085.     MOV    AX,BX
  1086.     MOV    BX,NEWSTK
  1087.     INC    NEWSTK
  1088.     ADD    BX,BX
  1089.     MOV    TABLE[BX],AX
  1090.     MOV    BX,AX
  1091.     POP    AX
  1092. PPBX:    OR    BX,BX
  1093.     RET
  1094. PPBXR:    MOV    AX,NEWSTK
  1095.     MOV    DI,OFFSET ORMSG+14
  1096.     CALL    DEC5OUT
  1097.     CALL    STRIP0
  1098.     MOV    DX,OFFSET ORMSG
  1099.     JMP    ERROUT
  1100. POPBX:    CMP    NEWSTK,0
  1101.     JZ    PPBXR
  1102.     DEC    NEWSTK
  1103.     MOV    BX,NEWSTK
  1104.     ADD    BX,BX
  1105.     MOV    BX,TABLE[BX]
  1106.     JMP    PPBX
  1107.  
  1108. FINDDIR:
  1109.     JCXZ    FINDDIR4
  1110. FINDDIR2:
  1111.     CMP    BYTE PTR [SI],'.'
  1112.     JE    FINDDIR3
  1113.     CMP    BYTE PTR [SI],0E5H
  1114.     JE    FINDDIR3
  1115.     CMP    BYTE PTR [SI],0
  1116.     JE    FINDDIR4
  1117.     TEST    BYTE PTR [SI+11],10H
  1118.     CLC
  1119.     JNZ    FINDDIR5
  1120. FINDDIR3:
  1121.     ADD    SI,32
  1122.     LOOP    FINDDIR2
  1123. FINDDIR4:
  1124.     STC
  1125. FINDDIR5:
  1126.     RET
  1127.  
  1128. SRCHCLST:
  1129.     PUSH    AX
  1130.     PUSH    CX
  1131.     PUSH    DI
  1132.     PUSH    SI
  1133.     MOV    SI,DIRBUF
  1134.     MOV    CX,DIR_LEN
  1135.     JCXZ    SRCHCLS3
  1136.     MOV    BX,CLUST
  1137. SRCHCLS1:
  1138.     CMP    BYTE PTR [SI],'.'
  1139.     JE    SRCHCLS2
  1140.     CMP    BYTE PTR [SI],0E5H
  1141.     JE    SRCHCLS2
  1142.     CMP    BYTE PTR [SI],0
  1143.     JE    SRCHCLS3
  1144.     CMP    BX,[SI+26]
  1145.     JE    SRCHCLS4
  1146. SRCHCLS2:
  1147.     ADD    SI,32
  1148.     LOOP    SRCHCLS1
  1149. SRCHCLS3:
  1150.     STC
  1151.     JMP    SHORT SRCHCLS5
  1152. SRCHCLS4:
  1153.     MOV    DI,OFFSET FNAME
  1154.     CALL    UNPARSE
  1155.     CLC
  1156. SRCHCLS5:
  1157.     POP    SI
  1158.     POP    DI
  1159.     POP    CX
  1160.     POP    AX
  1161.     RET
  1162.  
  1163. PREVCLST:
  1164.     PUSH    BX
  1165.     PUSH    CX
  1166.     PUSH    DX
  1167.     MOV    DX,BX
  1168.     MOV    CX,TOTCLST
  1169.     DEC    CX
  1170. PREVCLS1:
  1171.     MOV    BX,CX
  1172.     INC    BX
  1173.     CALL    NEXTCLST
  1174.     CMP    BX,DX
  1175.     LOOPNE    PREVCLS1
  1176.     JNE    PREVCLS2
  1177.     ADD    CX,2
  1178. PREVCLS2:
  1179.     MOV    AX,CX
  1180.     POP    DX
  1181.     POP    CX
  1182.     POP    BX
  1183.     RET
  1184.  
  1185. UNPARSE:
  1186.     PUSH    CX
  1187.     PUSH    DI
  1188.     PUSH    SI
  1189.     MOV    CX,8
  1190.     CALL    UNPARSE1
  1191.     MOV    AL,'.'
  1192.     STOSB
  1193.     POP    SI
  1194.     PUSH    SI
  1195.     ADD    SI,8
  1196.     MOV    CX,3
  1197.     CALL    UNPARSE1
  1198.     CMP    CX,3
  1199.     JNE    UNPARSE5
  1200.     DEC    DI
  1201. UNPARSE5:
  1202.     MOV    AL,0
  1203.     STOSB
  1204.     POP    SI
  1205.     POP    DI
  1206.     POP    CX
  1207.     RET
  1208. UNPARSE1:
  1209.     LODSB
  1210.     CMP    AL,' '
  1211.     JE    UNPARSE2
  1212.     STOSB
  1213.     LOOP    UNPARSE1
  1214. UNPARSE2:
  1215.     RET
  1216.  
  1217.  
  1218. MOVSTR: LODSB
  1219.     STOSB
  1220.     OR    AL,AL
  1221.     JNZ    MOVSTR
  1222.     RET
  1223.  
  1224. GET_WORD:
  1225.     PUSH    BX
  1226.     XOR    DX,DX
  1227. GET_WRD1:
  1228.     LODSB
  1229.     CMP    AL,'0'
  1230.     JB    GET_WRD2
  1231.     CMP    AL,'9'
  1232.     JA    GET_WRD2
  1233.     SUB    AL,'0'
  1234.     CBW
  1235.     MOV    BX,AX
  1236.     MOV    AX,10
  1237.     MUL    DX
  1238.     ADD    AX,BX
  1239.     MOV    DX,AX
  1240.     JMP    GET_WRD1
  1241. GET_WRD2:
  1242.     DEC    SI
  1243.     POP    BX
  1244.     RET
  1245.  
  1246. READCLST:
  1247.     PUSH    AX                ; Save Registers
  1248.     PUSH    CX
  1249.     PUSH    DX
  1250.     PUSH    BX                ; Save Registers
  1251.     PUSH    DI
  1252.     MOV    AX,BX                ; Calculate Absolute Sector #
  1253.     SUB    AX,2
  1254.     MOV    CX,CLSTSEC
  1255.     MUL    CX
  1256.     ADD    AX,STRTSEC
  1257.     MOV    DX,AX
  1258.     MOV    AL,DRIVE
  1259.     MOV    BX,DI                ; Read Cluster
  1260.     INT    25H
  1261.     JC    RCERR
  1262.     POPF
  1263.     POP    DI                ; Restore Registers
  1264.     POP    BX
  1265.     CALL    NEXTCLST            ; Get Next Cluster Number
  1266.     MOV    AX,CLSTSEC            ; Increment Buffer Pointer
  1267.     MUL    SECSIZE
  1268.     ADD    DI,AX
  1269.     JMP    SHORT RCCOM
  1270. RCERR:    POPF
  1271.     STC
  1272.     POP    DI
  1273.     POP    BX
  1274. RCCOM:    POP    DX                  ; Restore Registers
  1275.     POP    CX
  1276.     POP    AX
  1277.     RET                    ; Done
  1278.  
  1279. NEXTCLST:
  1280.     CMP    FATSIZE,3            ; If FAT Size = 16 Bits,
  1281.     JE    NEXTCLS1
  1282.     SHL    BX,1                ;   Simply Read Next Cluster #
  1283.     MOV    BX,FATBUF[BX]
  1284.     RET                    ;   Done
  1285. NEXTCLS1:
  1286.     PUSH    AX                ; Save Registers
  1287.     PUSH    CX
  1288.     MOV    AX,BX                ; Word # = Cluster # * 1.5
  1289.     SHL    AX,1
  1290.     ADD    BX,AX
  1291.     SHR    BX,1
  1292.     MOV    BX,FATBUF[BX]
  1293.     JNC    NEXTCLS2            ; If Odd, Use 12 MSB's
  1294.     MOV    CL,4
  1295.     SHR    BX,CL
  1296. NEXTCLS2:
  1297.     AND    BX,0FFFH            ; Else Use 12 LSB's
  1298.     POP    CX                ; Restore Registers
  1299.     POP    AX
  1300.     RET                    ; Done
  1301.  
  1302. STRIP:    LODSB                    ; Strip Off Leading Whitespace
  1303.     CMP    AL,' '
  1304.     JE    STRIP
  1305.     CMP    AL,9
  1306.     JE    STRIP
  1307.     OR    AL,AL                ; If End-of-Parameter, Error
  1308.     JNZ    NOERR1
  1309.     STC
  1310.     RET
  1311. NOERR1: DEC    SI                ; ReUse Last Character
  1312.     MOV    OPFLAG,0
  1313.     MOV    DI,OFFSET FSPEC         ; Point to FileSpec Buffer
  1314.     CALL    UPPER3
  1315.     CMP    BYTE PTR [SI+1],':'        ; If 2nd Character is Colon,
  1316.     JNE    GETPATH
  1317.     SUB    AL,'A'                ;   Get Drive Number
  1318.     MOV    DRIVE,AL
  1319.     ADD    SI,2                ;   and Scan Past
  1320. GETPATH:
  1321.     MOV    AL,DRIVE            ; Get Drive Number
  1322.     ADD    AL,'A'                ; Convert to Drive letter
  1323.     MOV    AH,':'                ; and Add Colon
  1324.     STOSW                    ; and place in FileSpec
  1325.     MOV    PARMSG+21,AL
  1326.     MOV    FRMSG2+19,AL
  1327.     CMP    BYTE PTR [SI],'\'        ; If Next Character is not '\',
  1328.     JE    COPYPATH
  1329.     MOV    AL,'\'
  1330.     STOSB
  1331.     PUSH    SI                ;   Get Current Path to FileSpec
  1332.     MOV    SI,DI
  1333.     MOV    AH,47H
  1334.     MOV    DL,DRIVE
  1335.     INC    DL
  1336.     INT    21H
  1337.     POP    SI
  1338.     MOV    AL,0                ;   Find End-of-FileSpec
  1339.     MOV    CX,64
  1340.     REPNE    SCASB
  1341.     JE    NOERR2
  1342.     JMP    ERROR
  1343. NOERR2: DEC    DI
  1344.     CMP    BYTE PTR [DI-1],'\'        ;   If Root DIR, Skip
  1345.     JE    COPYPATH
  1346.     MOV    AL,'\'                ;   End-of-FileSpec = '\'
  1347.     STOSB
  1348. COPYPATH:
  1349.     LODSB                    ; Copy Rest of Parameter
  1350.     CMP    AL,'/'                ; Until options
  1351.     JZ    GOTOPT
  1352.     CMP    AL,' '                ; Or end of filespec
  1353.     JZ    COPYDONE
  1354.     OR    AL,AL
  1355.     JZ    COPYDONE
  1356.     STOSB
  1357.     JMP    COPYPATH
  1358. GOTOPT: LODSB
  1359.     CALL    UPPER3
  1360.     TESTOP    BFOPAMUV,SETOPT
  1361.     JMP    ERROR
  1362. SETOPT: MOV    OPFLAG,AH
  1363.     INC    SI
  1364. COPYDONE:
  1365.     DEC    SI
  1366.     MOV    AL,0                ; Set End-of-FileSpec
  1367.     STOSB
  1368.     MOV    DX,OFFSET FSPEC         ; Convert to Upper Case
  1369.  
  1370. UPPER:    PUSH    AX                ; Save Registers
  1371.     PUSH    DI
  1372.     PUSH    SI
  1373.     MOV    SI,DX                ; Set Up Source Index
  1374.     MOV    DI,DX                ; Set Up Destination Index
  1375. UPPER1: LODSB                    ; Read From Source
  1376.     OR    AL,AL                ; If EOS, Done
  1377.     JZ    UPPER2
  1378.     CALL    UPPER3
  1379.     STOSB                    ; Save in Destination
  1380.     JMP    UPPER1                ; Repeat
  1381. UPPER2: POP    SI                ; Restore Registers
  1382.     POP    DI
  1383.     POP    AX
  1384.     RET                    ; Done
  1385. UPPER3: CMP    AL,'a'                ; If Lower Case,
  1386.     JL    UPPER4
  1387.     CMP    AL,'z'
  1388.     JG    UPPER4
  1389.     SUB    AL,'a'-'A'            ;   Convert to Upper Case
  1390. UPPER4: RET
  1391.  
  1392. OUT_CLST:
  1393.     PUSH    AX                ; Save Registers
  1394.     PUSH    DX
  1395.     PUSH    DI
  1396.     MOV    DI,OFFSET CLSTSTR+5        ; Convert Cluster # to Decimal
  1397.     CALL    DEC5OUT
  1398.     CALL    STRIP0                ; Strip Off Leading Zeroes
  1399.     MOV    DI,OFFSET CLSTSTR        ; Output Cluster Number
  1400.     MOV    AH,5
  1401. OUT_CLS0:
  1402.     CMP    BYTE PTR [DI],' '
  1403.     JNZ    OUT_CLS1
  1404.     INC    DI
  1405.     DEC    AH
  1406.     JMP    OUT_CLS0
  1407. OUT_CLS1:
  1408.     MOV    DX,DI
  1409.     CALL    DOS9
  1410.     POP    DI                ; Restore Registers
  1411.     POP    DX
  1412.     POP    AX
  1413.     RET                    ; Done
  1414.  
  1415. STRIP0: CMP    BYTE PTR [DI],'0'        ; If Character != '0', Done
  1416.     JNE    STRIP1
  1417.     CMP    BYTE PTR [DI+1],'0'        ; If Next Character != Digit,
  1418.     JL    STRIP1                ;   Done
  1419.     CMP    BYTE PTR [DI+1],'9'
  1420.     JG    STRIP1
  1421.     MOV    BYTE PTR [DI],' '        ; Change '0' to ' '
  1422.     INC    DI                ; Point to Next Character
  1423.     JMP    STRIP0                ; Repeat
  1424. STRIP1: RET                    ; Done
  1425.  
  1426. DEC2OUT:
  1427.     PUSH    AX                ; Save Registers
  1428.     PUSH    BX
  1429. D2O1:    XOR    AH,AH                ; Clear AH
  1430.     MOV    BL,10                ; AH=AX%10,AL=AX/10
  1431.     DIV    BL
  1432.     ADD    AX,'00'             ; Convert to ASCII
  1433.     SUB    DI,2
  1434.     MOV    [DI],AX             ; Store in String
  1435.     POP    BX                ; Restore Registers
  1436.     POP    AX
  1437.     RET                    ; Done
  1438.  
  1439. DEC4OUT:
  1440.     PUSH    AX                ; Save Registers
  1441.     PUSH    BX
  1442. D4O1:    MOV    BL,100                ; AH=AX%100,AL=AX/100
  1443.     DIV    BL
  1444.     XCHG    AH,AL                ; Convert 2 LSD's
  1445.     CALL    DEC2OUT
  1446.     XCHG    AH,AL                ; Convert 2 MSD's
  1447.     JMP    D2O1                ; Using common code
  1448.  
  1449. DEC5OUT:
  1450.     PUSH    AX                ; Save Registers
  1451.     PUSH    BX
  1452.     PUSH    DX                ; DX=AX%10000,AX=AX/10000
  1453.     MOV    BX,10000
  1454.     XOR    DX,DX
  1455.     DIV    BX
  1456.     XCHG    DX,AX                ; Convert 4 LSD's
  1457.     CALL    DEC4OUT
  1458.     ADD    DL,'0'                ; Convert MSD
  1459.     DEC    DI
  1460.     MOV    [DI],DL
  1461.     POP    DX                ; Restore Registers
  1462.     POP    BX
  1463.     POP    AX
  1464.     RET                    ; Done
  1465.  
  1466. DEC8OUT:
  1467.     PUSH    AX                ; Save Registers
  1468.     PUSH    BX
  1469.     PUSH    DX
  1470.     MOV    BX,10000            ; DX=DX:AX%10000,AX=DX:AX/10000
  1471.     DIV    BX
  1472.     XCHG    DX,AX                ; Convert 4 LSD's
  1473.     CALL    DEC4OUT
  1474.     XCHG    DX,AX                ; Convert 4 MSD's
  1475.     POP    DX
  1476.     JMP    D4O1                ; Using common code
  1477.  
  1478. TABLE    LABEL    WORD
  1479. FATBUF    EQU    TABLE+8192
  1480.  
  1481. CODE    ENDS
  1482.  
  1483.     END    CHAIN
  1484. vert 4 MSD's
  1485.     POP    DX
  1486.     JMP    D4O1                ; Using common code
  1487.  
  1488. TABLE    LABEL    WORD
  1489. FATBUF    EQU    TABLE+8192
  1490.  
  1491. COD